Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
@opentelemetry/instrumentation
Advanced tools
Base class for node which OpenTelemetry instrumentation modules extend
The @opentelemetry/instrumentation package is part of the OpenTelemetry project, which aims to provide a unified and standardized observability framework for monitoring applications' performance and behavior. This particular package offers a way to automatically instrument code to collect telemetry data such as traces and metrics, making it easier to monitor and debug applications.
Automatic Instrumentation
Automatically instruments Node.js applications to collect telemetry data, such as tracing information for HTTP requests. This example shows how to set up the NodeTracerProvider and register the HttpInstrumentation to start collecting data.
const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node');
const { registerInstrumentations } = require('@opentelemetry/instrumentation');
const { HttpInstrumentation } = require('@opentelemetry/instrumentation-http');
const provider = new NodeTracerProvider();
registerInstrumentations({
instrumentations: [
new HttpInstrumentation()
],
tracerProvider: provider,
});
Custom Instrumentation
Enables the creation of custom instrumentation for any library or application code not covered by the existing instrumentations. This example demonstrates how to extend the InstrumentationBase class to create a custom instrumentation.
const { InstrumentationBase } = require('@opentelemetry/instrumentation');
class MyCustomInstrumentation extends InstrumentationBase {
constructor() {
super('MyCustomInstrumentation');
}
init() {
// Custom initialization logic
}
}
Jaeger client is a package for distributed tracing in microservices architecture. It can be used to monitor and troubleshoot transactions in complex distributed systems. Compared to @opentelemetry/instrumentation, jaeger-client is more specific to the Jaeger backend, whereas OpenTelemetry provides a more vendor-neutral approach, allowing data to be exported to various backends including Jaeger.
Note: This is an experimental package under active development. New releases may include breaking changes.
Note: Much of OpenTelemetry JS documentation is written assuming the compiled application is run as CommonJS. For more details on ECMAScript Modules vs CommonJS, refer to esm-support.
npm install --save @opentelemetry/instrumentation
import {
InstrumentationBase,
InstrumentationConfig,
InstrumentationNodeModuleDefinition,
InstrumentationNodeModuleFile,
} from '@opentelemetry/instrumentation';
import type * as module_name_to_be_patched from 'module_name_to_be_patched';
export class MyInstrumentation extends InstrumentationBase {
constructor(config: InstrumentationConfig = {}) {
super('MyInstrumentation', VERSION, config);
}
/**
* Init method will be called when the plugin is constructed.
* It returns an `InstrumentationNodeModuleDefinition` which describes
* the node module to be instrumented and patched.
* It may also return a list of `InstrumentationNodeModuleDefinition`s if
* the plugin should patch multiple modules or versions.
*/
protected init() {
const module = new InstrumentationNodeModuleDefinition(
'module_name_to_be_patched',
['1.*'],
this._onPatchMain,
this._onUnPatchMain,
);
// in case you need to patch additional files - this is optional
module.files.push(this._addPatchingMethod());
return module;
// you can also define more modules then just return an array of modules
// return [module1, module2, ....]
}
private _onPatchMain(moduleExports: typeof module_name_to_be_patched) {
this._wrap(
moduleExports,
'mainMethodName',
this._patchMainMethodName()
);
return moduleExports;
}
private _onUnPatchMain(moduleExports: typeof module_name_to_be_patched) {
this._unwrap(moduleExports, 'mainMethodName');
}
private _addPatchingMethod(): InstrumentationNodeModuleFile {
const file = new InstrumentationNodeModuleFile(
'module_name_to_be_patched/src/some_file.js',
this._onPatchMethodName,
this._onUnPatchMethodName,
);
return file;
}
private _onPatchMethodName(moduleExports: typeof module_name_to_be_patched) {
this._wrap(
moduleExports,
'methodName',
this._patchMethodName()
);
return moduleExports;
}
private _onUnPatchMethodName(moduleExports: typeof module_name_to_be_patched) {
this._unwrap(moduleExports, 'methodName');
}
private _patchMethodName(): (original) => any {
const plugin = this;
return function methodName(original) {
return function patchMethodName(this: any): PromiseOrValue<module_name_to_be_patched.methodName> {
console.log('methodName', arguments);
return original.apply(this, arguments);
};
};
}
private _patchMainMethodName(): (original) => any {
const plugin = this;
return function mainMethodName(original) {
return function patchMainMethodName(this: any): PromiseOrValue<module_name_to_be_patched.mainMethodName> {
console.log('mainMethodName', arguments);
return original.apply(this, arguments);
};
};
}
}
// Later, but before the module to instrument is required
const myInstrumentation = new MyInstrumentation();
myInstrumentation.setTracerProvider(provider); // this is optional, only if global TracerProvider shouldn't be used
myInstrumentation.setMeterProvider(meterProvider); // this is optional
myInstrumentation.enable();
// or use Auto Loader
import {
InstrumentationBase,
InstrumentationConfig,
} from '@opentelemetry/instrumentation';
import { Instrumentation } from '@opentelemetry/instrumentation';
export class MyInstrumentation extends InstrumentationBase {
constructor(config: InstrumentationConfig = {}) {
super('MyInstrumentation', VERSION, config);
}
private _patchOpen() {
return (original: OpenFunction): OpenFunction => {
const plugin = this;
return function patchOpen(this: XMLHttpRequest, ...args): void {
console.log('open', arguments);
return original.apply(this, args);
};
};
}
public enable() {
this._wrap(XMLHttpRequest.prototype, 'open', this._patchOpen());
}
public disable() {
this._unwrap(XMLHttpRequest.prototype, 'open');
}
}
// Later
const myInstrumentation = new MyInstrumentation();
myInstrumentation.setTracerProvider(provider); // this is optional, only if global TracerProvider shouldn't be used
myInstrumentation.setMeterProvider(meterProvider); // this is optional, only if global MeterProvider shouldn't be used
myInstrumentation.enable();
// or use Auto Loader
const { B3Propagator } = require('@opentelemetry/propagator-b3');
const { registerInstrumentations } = require('@opentelemetry/instrumentation');
const { HttpInstrumentation } = require('@opentelemetry/instrumentation-http');
const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node');
const tracerProvider = new NodeTracerProvider();
tracerProvider.register({
propagator: new B3Propagator(),
});
registerInstrumentations({
instrumentations: [
new HttpInstrumentation(),
],
//tracerProvider: tracerProvider, // optional, only if global TracerProvider shouldn't be used
//meterProvider: meterProvider, // optional, only if global MeterProvider shouldn't be used
});
const { B3Propagator } = require('@opentelemetry/propagator-b3');
const { registerInstrumentations } = require('@opentelemetry/instrumentation');
const { XMLHttpRequestInstrumentation } = require('@opentelemetry/instrumentation-xml-http-request');
const { WebTracerProvider } = require('@opentelemetry/sdk-trace-web');
const tracerProvider = new WebTracerProvider();
tracerProvider.register({
propagator: new B3Propagator(),
});
registerInstrumentations({
instrumentations: [
new XMLHttpRequestInstrumentation({
ignoreUrls: [/localhost/],
propagateTraceHeaderCorsUrls: [
'http://localhost:8090',
],
}),
],
//tracerProvider: tracerProvider, // optional, only if global TracerProvider shouldn't be used
//meterProvider: meterProvider, // optional, only if global MeterProvider shouldn't be used
});
The registerInstrumentations()
API allows to specify which TracerProvider
and/or MeterProvider
to use by the given options object.
If nothing is specified the global registered provider is used. Usually this is what most users want therefore it's recommended to keep this default.
There might be use case where someone has the need for more providers within an application. Please note that special care must be takes in such setups
to avoid leaking information from one provider to the other because there are a lot places where e.g. the global ContextManager
or Propagator
is used.
Node.js uses a different module loader for ECMAScript Modules (ESM) vs. CommonJS (CJS).
A require()
call will cause Node.js to use the CommonJS module loader.
An import ...
statement or import()
call will cause Node.js to use the ECMAScript module loader.
If your application is written in JavaScript as ESM, or it must compile to ESM from TypeScript, then a loader hook is required to properly patch instrumentation.
The custom hook for ESM instrumentation is --experimental-loader=@opentelemetry/instrumentation/hook.mjs
.
This flag must be passed to the node
binary, which is often done as a startup command and/or in the NODE_OPTIONS
environment variable.
For more details on ECMAScript Modules vs CommonJS, refer to esm-support.
Instrumentations for external modules (e.g. express, mongodb,...) hooks the require
call or import
statement. Therefore following conditions need to be met that this mechanism can work:
require
ed (CJS only)esbuild
, webpack
, ... usually have some mechanism to exclude specific modules from bundlingApache 2.0 - See LICENSE for more information.
FAQs
Base class for node which OpenTelemetry instrumentation modules extend
The npm package @opentelemetry/instrumentation receives a total of 11,924,680 weekly downloads. As such, @opentelemetry/instrumentation popularity was classified as popular.
We found that @opentelemetry/instrumentation demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.